<template>
	<div class="tree-graph-container">
		<div ref="mindMapContainerRef" class="tree-graph-canvas"></div>

		<!-- 右键菜单 -->
		<div
			ref="contextMenuRef"
			class="context-menu"
			v-show="contextMenuVisible"
			:style="contextMenuStyle"
			@click.stop
		>
			<div class="context-menu-item" @click="insertSiblingNode">
				<span class="menu-icon">⊞</span>
				<span class="menu-text">插入同级节点</span>
			</div>
			<div class="context-menu-item" @click="insertChildNode">
				<span class="menu-icon">└</span>
				<span class="menu-text">插入子级节点</span>
			</div>
			<div class="context-menu-item" @click="insertParentNode">
				<span class="menu-icon">┌</span>
				<span class="menu-text">插入父级节点</span>
			</div>
			<div class="context-menu-divider"></div>
			<div class="context-menu-item danger" @click="deleteNodeWithChildren">
				<span class="menu-icon">🗑</span>
				<span class="menu-text">删除节点</span>
			</div>
			<div class="context-menu-item danger" @click="deleteCurrentNodeOnly">
				<span class="menu-icon">✂</span>
				<span class="menu-text">仅删除当前节点</span>
			</div>
		</div>

		<!-- 节点信息气泡框 -->
		<div ref="nodeTooltipRef" class="node-tooltip" v-show="tooltipVisible" :style="tooltipStyle">
			<div class="tooltip-content">
				<div class="tooltip-title">{{ tooltipData.name }}</div>
				<div class="tooltip-type">类型：{{ tooltipData.type }}</div>
			</div>
			<div class="tooltip-arrow"></div>
		</div>
	</div>
</template>

<script setup lang="ts">
import MindMap from 'simple-mind-map';
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
import type {
	TreeDataItemType,
	NodeItemType,
	ThemeConfigType,
	ThemeColorType,
	TreeNodeDataType,
	TreeNodeElType,
	MultiGradientConfig,
	MultiGradientConfigItem,
	GradientStop,
	CustomMouseEvent,
	MindMapNodeEvent,
	MindMapTextEditElement,
	DataChangeEvent,
	NodeFindCondition,
	NodeContextMenuEvent,
	NodeDataForAdd,
	LinkDataForAdd,
	NodeDataForAddPatch,
	UpdateNodeData
} from './TreeGraph.type';

const props = withDefaults(
	defineProps<{
		treeData: TreeDataItemType;
		themeConfig?: ThemeConfigType;
		colorMode?: 'level' | 'type';
		isEdit?: boolean;
		defaultExpandLevel?: number | 'all'; // 默认展开的层级，数字表示展开到第几层，'all' 表示全部展开
		// 不参与高亮的节点 ID 列表，当搜索时，这些节点不会参与高亮
		excludeNodeList?: string[];
		// 节点类型映射（用于气泡框显示中文）
		typeMap?: Map<string, string>;
		// 缩放初始值（百分比，20-400，默认100）
		zoomValue?: number;
	}>(),
	{
		treeData: () => ({ nodes: [], links: [] }),
		themeConfig: () => ({}),
		colorMode: 'level',
		isEdit: false,
		defaultExpandLevel: undefined,
		excludeNodeList: () => [],
		typeMap: () => new Map(),
		zoomValue: 100
	}
);

// 内部数据副本，用于动态修改
const internalTreeData = ref<TreeNodeDataType | null>(null);
// 存储父子关系映射（从 convertToMindMapData 中获取）
const relationMaps = ref<{
	parentMap: Map<string, string>; // 子节点ID -> 父节点ID
	childrenMap: Map<string, string[]>; // 父节点ID -> 子节点ID数组
	nodeLevelMap: Map<string, number>; // 节点ID -> 层级（从0开始）
}>({
	parentMap: new Map(),
	childrenMap: new Map(),
	nodeLevelMap: new Map()
});
// 思维导图实例
const mindMapInstance = ref<MindMap | null>(null);

onMounted(() => {
	// 等待下一个tick再初始化，确保props已经传入
	nextTick(() => {
		// 从 CSS 变量中读取主题颜色
		loadColorVariables();
	});
});

onBeforeUnmount(() => {
	// 清理节点悬停事件监听器
	cleanupNodeHoverEvents();

	// 清理键盘事件监听器
	cleanupKeyboardEventListeners();

	// 清理全局事件监听器
	cleanupGlobalEventListeners();

	// 销毁思维导图实例
	if (mindMapInstance.value) {
		try {
			mindMapInstance.value.destroy();
		} catch (error) {
			console.error('销毁思维导图实例时出错:', error);
		}
	}

	console.log('Mind组件已卸载，所有资源已清理');
});

// 标记是否为首次渲染
const isFirstRender = ref(true);

watch(
	() => props.treeData,
	(newData) => {
		if (newData && (newData.nodes.length || newData.links.length)) {
			nextTick(() => {
				// 更新内部数据副本
				initInternalData(newData);
				// 计算缓存
				buildNodeCache();

				if (internalTreeData.value) {
					// 数据更新时重置首次渲染标记，以便重新居中显示
					isFirstRender.value = true;
					if (mindMapInstance.value) {
						// 如果思维导图已初始化，则重新渲染
						mindMapInstance.value.setData(internalTreeData.value);
						(mindMapInstance.value.render as () => void)();
					} else {
						// 如果思维导图未初始化，则初始化思维导图
						initMindMap(internalTreeData.value);
					}
				}
			});
		}
	},
	{
		deep: true,
		immediate: true
	}
);

const emit = defineEmits<{
	(e: 'node-click', node: MindMapNodeEvent): void;
	(e: 'node-context-menu-action', event: NodeContextMenuEvent): void;
	(e: 'update:zoomValue', value: number): void;
}>();

const mindMapContainerRef = ref<HTMLElement | null>(null);
const contextMenuRef = ref<HTMLElement | null>(null);
// 主题颜色变量（从 CSS 变量中读取）
const colorBrand = ref('#674fde');
// 从 CSS 变量中加载颜色值
const loadColorVariables = () => {
	try {
		const container = mindMapContainerRef.value;
		if (container && container.parentElement) {
			const styles = getComputedStyle(container.parentElement);
			const brandColor = styles.getPropertyValue('--color-brand').trim();
			if (brandColor) {
				colorBrand.value = brandColor;
			}
		}
	} catch (error) {
		console.error('加载 CSS 变量失败，使用默认颜色:', error);
	}
};

/** -------------------缩放功能------------------- */
// 内部缩放值（百分比）
const internalZoomValue = ref(props.zoomValue || 100);
// 标记是否正在通过程序设置缩放（避免循环更新）
const isApplyingZoom = ref(false);

// 将百分比转换为 simple-mind-map scale
// zoomValue: 20-400 (百分比，对应 scale 2-4)
// simple-mind-map 的缩放范围通常是 0.2-4
const zoomValueToScale = (zoomValue: number): number => {
	// 线性映射：20% -> 0.2, 100% -> 1.0, 400% -> 4.0
	const scale = zoomValue / 100;
	return Math.max(0.2, Math.min(4, scale));
};

// 将 simple-mind-map scale 转换为百分比
const scaleToZoomValue = (scale: number): number => {
	// scale -> zoomValue (百分比)
	const zoomValue = scale * 100;
	return Math.max(20, Math.min(400, Math.round(zoomValue)));
};

// 根据 zoomValue 应用缩放
const applyZoomFromValue = (zoomValue: number) => {
	if (!mindMapInstance.value) return;

	isApplyingZoom.value = true;
	const targetScale = zoomValueToScale(zoomValue);

	try {
		// simple-mind-map 的 view API
		const view = mindMapInstance.value.view as unknown as {
			scale?: number;
			setTransform?: (scale: number, x: number, y: number) => void;
			setScale?: (scale: number) => void;
		};

		// 尝试使用 setScale 方法
		if (view.setScale && typeof view.setScale === 'function') {
			view.setScale(targetScale);
		} else if (view.setTransform && typeof view.setTransform === 'function') {
			// 获取当前变换数据
			const transformData = (
				view as { getTransformData?: () => { transform: { x: number; y: number } } }
			).getTransformData?.();
			const currentX = transformData?.transform?.x || 0;
			const currentY = transformData?.transform?.y || 0;
			view.setTransform(targetScale, currentX, currentY);
		} else {
			// 直接设置 scale 属性（如果 view.scale 是属性）
			if (typeof view.scale === 'number') {
				(view as { scale: number }).scale = targetScale;
				// 触发重新渲染
				if (mindMapInstance.value.render) {
					(mindMapInstance.value.render as () => void)();
				}
			}
		}

		// 延迟重置标记，确保缩放完成
		setTimeout(() => {
			isApplyingZoom.value = false;
		}, 100);
	} catch (error) {
		console.error('应用缩放失败:', error);
		isApplyingZoom.value = false;
	}
};

/** -------------------初始化数据------------------- */
// 初始化内部数据副本
const initInternalData = (treeData: TreeDataItemType) => {
	const result = convertToMindMapData(JSON.parse(JSON.stringify(treeData)));
	internalTreeData.value = result.treeData;
	relationMaps.value = {
		parentMap: result.parentMap,
		childrenMap: result.childrenMap,
		nodeLevelMap: result.nodeLevelMap
	};
};

/**
 * 将网络图平级数据转换为树图层级数据
 * @param networkData 网络图数据 { nodes: [], links: [] }
 * @returns 包含树图数据和映射关系的对象
 */
const convertToMindMapData = (networkData: TreeDataItemType) => {
	const { nodes, links } = networkData;

	// 1. 筛选出层级关系的连接（isHierarchy 为 true）
	const hierarchyLinks = links.filter((link) => link.isHierarchy);

	// 2. 构建父子关系映射
	const childrenMap = new Map<string, string[]>(); // 父节点ID -> 子节点ID数组
	const parentMap = new Map<string, string>(); // 子节点ID -> 父节点ID

	hierarchyLinks.forEach((link) => {
		const sourceId =
			typeof link.source === 'object' ? (link.source as { id: string }).id : link.source;
		const targetId =
			typeof link.target === 'object' ? (link.target as { id: string }).id : link.target;

		// 添加到父子映射
		if (!childrenMap.has(sourceId)) {
			childrenMap.set(sourceId, []);
		}
		childrenMap.get(sourceId)!.push(targetId);

		// 添加到子父映射
		parentMap.set(targetId, sourceId);
	});

	// 3. 查找根节点（没有父节点的节点）
	const rootNodeIds = nodes.map((node) => node.id).filter((nodeId) => !parentMap.has(nodeId));

	// 如果没有明确的根节点，选择入度最小的节点作为根节点
	let rootNodeId: string;
	if (rootNodeIds.length === 0) {
		console.warn('未找到明确的根节点，选择第一个节点作为根节点');
		rootNodeId = nodes[0]?.id;
	} else if (rootNodeIds.length > 1) {
		// 如果有多个根节点，选择出度最大的作为根节点
		console.warn('发现多个根节点，选择出度最大的节点作为根节点');
		rootNodeId = rootNodeIds.reduce((maxNode, nodeId) => {
			const currentOutDegree = childrenMap.get(nodeId)?.length || 0;
			const maxOutDegree = childrenMap.get(maxNode)?.length || 0;
			return currentOutDegree > maxOutDegree ? nodeId : maxNode;
		});
	} else {
		rootNodeId = rootNodeIds[0];
	}

	// 4. 构建节点映射
	const nodeMap = new Map<string, NodeItemType>();
	nodes.forEach((node) => {
		nodeMap.set(node.id, node);
	});

	// 5. 递归构建树结构
	const buildTreeNode = (
		nodeId: string,
		visited = new Set<string>(),
		level = 0
	): TreeNodeDataType | null => {
		// 防止循环引用
		if (visited.has(nodeId)) {
			console.warn(`检测到循环引用，跳过节点: ${nodeId}`);
			return null;
		}

		const node = nodeMap.get(nodeId);
		if (!node) {
			console.warn(`节点不存在: ${nodeId}`);
			return null;
		}

		visited.add(nodeId);

		// 根据 defaultExpandLevel 设置 expand 属性
		let expand: boolean | undefined = undefined;
		if (props.defaultExpandLevel !== undefined) {
			if (props.defaultExpandLevel === 'all') {
				// 全部展开
				expand = true;
			} else {
				// 数字表示展开到第几层（level 从 0 开始，根节点是第 0 层）
				// 如果当前层级小于目标层级，则展开
				expand = level < props.defaultExpandLevel;
			}
		}

		const treeNode: TreeNodeDataType = {
			data: {
				id: node.id,
				uid: node.id,
				text: node.label,
				type: node.type,
				expand
			}
		};

		// 获取子节点ID列表
		const childIds = childrenMap.get(nodeId) || [];

		if (childIds.length > 0) {
			treeNode.children = childIds
				.map((childId) => buildTreeNode(childId, new Set(visited), level + 1))
				.filter((child) => child !== null); // 过滤掉循环引用的节点
		}

		return treeNode;
	};

	// 6. 计算节点层级映射（类似网图的实现）
	const nodeLevelMap = new Map<string, number>(); // 节点ID -> 层级（从0开始）

	// 递归计算节点层级
	const calculateLevel = (nodeId: string, visited = new Set<string>()): number => {
		if (visited.has(nodeId)) {
			// 循环引用，返回已计算的层级或0
			return nodeLevelMap.get(nodeId) || 0;
		}

		if (nodeLevelMap.has(nodeId)) {
			return nodeLevelMap.get(nodeId)!;
		}

		visited.add(nodeId);
		const parentId = parentMap.get(nodeId);

		if (!parentId) {
			// 根节点，层级为0
			nodeLevelMap.set(nodeId, 0);
			return 0;
		}

		// 父节点的层级 + 1
		const parentLevel = calculateLevel(parentId, visited);
		const level = parentLevel + 1;
		nodeLevelMap.set(nodeId, level);
		return level;
	};

	// 为所有节点计算层级
	nodes.forEach((node) => {
		if (!nodeLevelMap.has(node.id)) {
			calculateLevel(node.id);
		}
	});

	// 7. 从根节点开始构建树
	const treeData = buildTreeNode(rootNodeId);

	if (!treeData) {
		console.error('树数据构建失败');
		// 返回一个默认的单节点树
		return {
			treeData: {
				data: {
					text: nodes[0]?.label || '根节点',
					type: nodes[0]?.type || '',
					id: nodes[0]?.id || 'root',
					uid: nodes[0]?.id || 'root'
				},
				children: []
			},
			parentMap,
			childrenMap,
			nodeLevelMap
		};
	}

	console.log('树图数据转换完成:', treeData);
	return {
		treeData,
		parentMap,
		childrenMap,
		nodeLevelMap
	};
};

/** -------------------思维导图渲染------------------- */
// 初始化思维导图
const initMindMap = async (treeData: TreeNodeDataType) => {
	if (!mindMapContainerRef.value) return;

	try {
		// 默认主题配置
		const defaultThemeConfig: ThemeConfigType = {
			lineWidth: 2,
			lineColor: '#D3D6E3',
			// 曲线连接
			lineStyle: 'curve',
			// 曲线连接时，根节点和其他节点的连线起始位置保持统一，默认根节点的连线起始位置在节点中心，其他节点在节点右侧（或左侧），如果该配置设为true，那么根节点的连线起始位置也会在节点右侧（或左侧）
			rootLineStartPositionKeepSameInCurve: true,
			root: {
				shape: 'rectangle',
				fillColor: '#4A90E2',
				borderWidth: 0,
				color: '#ffffff',
				fontSize: 16,
				fontWeight: 600,
				paddingX: 20,
				paddingY: 12,
				borderRadius: 8,
				fontFamily: 'Alibaba PuHuiTi'
			},
			second: {
				shape: 'rectangle',
				fillColor: '#7ED321',
				borderWidth: 0,
				color: '#ffffff',
				fontSize: 14,
				fontWeight: 500,
				paddingX: 20,
				paddingY: 10,
				borderRadius: 6,
				fontFamily: 'Alibaba PuHuiTi'
			},
			node: {
				shape: 'rectangle',
				marginY: 20,
				fillColor: '#F5A623',
				borderWidth: 0,
				color: '#ffffff',
				fontSize: 12,
				fontWeight: 400,
				paddingX: 20,
				paddingY: 10,
				borderRadius: 4,
				fontFamily: 'Alibaba PuHuiTi'
			}
		};

		const finalThemeConfig = mergeThemeConfig(defaultThemeConfig, props.themeConfig);

		// 处理多段渐变配置：将多段渐变转换为库支持的单段渐变（用于初始化）
		preprocessMultiGradientConfig(finalThemeConfig);

		// 创建思维导图实例
		mindMapInstance.value = new MindMap({
			el: mindMapContainerRef.value,
			data: treeData,
			themeConfig: finalThemeConfig,
			mousewheelAction: 'zoom', // 鼠标滚动缩放
			openPerformance: true,
			// 编辑模式配置
			readonly: !props.isEdit,
			// 缩放范围配置：最小 20，最大 400
			minZoomRatio: 20,
			maxZoomRatio: 400
		} as unknown as ConstructorParameters<typeof MindMap>[0]);

		// 绑定事件
		bindMindMapEvents();

		// 添加全局点击事件监听器，用于隐藏右键菜单
		addGlobalEventListeners();

		// 彻底禁用键盘快捷键
		disableAllKeyboardShortcuts();

		// 彻底禁用节点编辑功能
		disableNodeEditing();

		// 应用初始缩放值
		nextTick(() => {
			if (props.zoomValue !== undefined) {
				applyZoomFromValue(props.zoomValue);
			}
		});
	} catch (error) {
		console.error('思维导图初始化失败:', error);
	}
};

// 深度合并主题配置
const mergeThemeConfig = (defaultConfig: ThemeConfigType, customConfig: ThemeConfigType) => {
	const merged: ThemeConfigType = { ...defaultConfig };
	const defaultConfigRecord = defaultConfig as Record<string, unknown>;
	const customConfigRecord = customConfig as Record<string, unknown>;
	const mergedRecord = merged as Record<string, unknown>;

	for (const key in customConfig) {
		if (Object.prototype.hasOwnProperty.call(customConfig, key)) {
			if (
				typeof customConfigRecord[key] === 'object' &&
				customConfigRecord[key] !== null &&
				typeof defaultConfigRecord[key] === 'object' &&
				defaultConfigRecord[key] !== null
			) {
				// 深度合并对象
				mergedRecord[key] = {
					...(defaultConfigRecord[key] as Record<string, unknown>),
					...(customConfigRecord[key] as Record<string, unknown>)
				};
			} else {
				// 直接赋值
				mergedRecord[key] = customConfigRecord[key];
			}
		}
	}

	return merged;
};

// 多段渐变配置存储
const multiGradientConfigs = ref<MultiGradientConfig>({
	root: null,
	second: null,
	node: null
});
// 预处理多段渐变配置
const preprocessMultiGradientConfig = (themeConfig: ThemeConfigType) => {
	// 检查并保存各层级的多段渐变配置
	['root', 'second', 'node'].forEach((level) => {
		const config: ThemeColorType | undefined = themeConfig[level as 'root' | 'second' | 'node'];
		if (config && config.gradientStyle === 'multi') {
			// 检查是否有完整的渐变配置
			if (
				config.gradientStops &&
				Array.isArray(config.gradientStops) &&
				config.gradientStops.length >= 2
			) {
				// 保存多段渐变配置
				multiGradientConfigs.value[level as 'root' | 'second' | 'node'] = {
					gradientStops: config.gradientStops,
					gradientDir: config.gradientDir || [0, 0, 1, 0] // 默认水平渐变
				};

				// 将第一个颜色作为临时填充色（库初始化需要）
				config.fillColor = config.gradientStops[0].color;
				// 删除库不支持的自定义属性
				delete config.gradientStyle;
				delete config.gradientStops;
				delete config.gradientDir;
			} else {
				// 配置不完整，删除 gradientStyle 避免干扰 simple-mind-map 库
				console.warn(
					`[TreeGraph] 节点层级 "${level}" 的 gradientStyle 设置为 'multi' 但 gradientStops 配置不完整（需要至少2个色标），已忽略该配置，将使用 fillColor。`
				);
				delete config.gradientStyle;
				delete config.gradientStops;
				delete config.gradientDir;
			}
		}
	});
};

/** -------------------绑定思维导图事件------------------- */
// 用于区分点击和拖动的状态
const mouseDownInfo = ref<{
	isDown: boolean;
	startX: number;
	startY: number;
	hasMoved: boolean;
}>({
	isDown: false,
	startX: 0,
	startY: 0,
	hasMoved: false // 标记是否发生了移动
});
// 绑定思维导图事件
const bindMindMapEvents = () => {
	if (!mindMapInstance.value) return;

	// 用于防止事件冒泡的标记
	let isNodeClicked = false;

	// 节点的单击事件
	mindMapInstance.value.on('node_click', (node: MindMapNodeEvent) => {
		isNodeClicked = true;

		if (node?.uid) {
			// 内部调用时不采用居中策略
			highlightNodeAndChildrenByNodeId(node.uid, false);
			emit('node-click', node);
		}

		// 重置标记，延迟一点确保其他事件处理完成
		setTimeout(() => {
			isNodeClicked = false;
		}, 10);
	});

	// 节点的双击事件
	mindMapInstance.value.on('node_dblclick', (node: MindMapNodeEvent, e: CustomMouseEvent) => {
		console.log('节点的双击事件:', node);
		isNodeClicked = true;

		// 阻止默认的双击编辑行为
		if (e && typeof e.preventDefault === 'function') {
			e.preventDefault();
			e.stopPropagation();
		}

		// 确保不进入编辑模式
		if (mindMapInstance.value && mindMapInstance.value.renderer) {
			// 取消任何可能的文本编辑状态
			mindMapInstance.value.renderer.textEdit?.hideEditTextBox();
		}

		console.log('双击编辑已被禁用');

		// 重置标记
		setTimeout(() => {
			isNodeClicked = false;
		}, 10);
	});

	// 节点的右键事件
	mindMapInstance.value.on('node_contextmenu', (e: CustomMouseEvent, node: MindMapNodeEvent) => {
		console.log('节点的右键事件:', node);
		e.preventDefault(); // 阻止默认右键菜单
		e.stopPropagation(); // 阻止事件冒泡

		// 获取鼠标位置
		const { clientX: x, clientY: y } = e;

		// 显示自定义右键菜单
		showContextMenu(x, y, node);
	});

	// 渲染树数据变化，可以监听该方法获取最新数据
	mindMapInstance.value.on('data_change', (data: DataChangeEvent) => {
		console.log('渲染树数据变化:', data);
	});

	// 节点文本编辑框显示事件 - 强制禁用编辑
	mindMapInstance.value.on(
		'show_text_edit',
		(node: MindMapNodeEvent, textEditElement: MindMapTextEditElement) => {
			console.log('检测到文本编辑尝试，已被禁用', node);

			// 立即隐藏编辑框
			if (
				mindMapInstance.value &&
				mindMapInstance.value.renderer &&
				mindMapInstance.value.renderer.textEdit
			) {
				// 使用setTimeout确保在下一个事件循环中执行，避免时序问题
				setTimeout(() => {
					mindMapInstance.value?.renderer.textEdit.hideEditTextBox();
				}, 0);
			}

			// 如果有传入的编辑元素，直接隐藏
			if (textEditElement && textEditElement.style) {
				textEditElement.style.display = 'none';
			}
		}
	);

	// 节点文本编辑框关闭事件
	mindMapInstance.value.on(
		'hide_text_edit',
		(
			textEditNode: MindMapNodeEvent,
			activeNodeList: MindMapNodeEvent[],
			node: MindMapNodeEvent
		) => {
			console.log('节点文本编辑框关闭事件:', textEditNode, activeNodeList, node);
		}
	);

	// 节点树渲染完毕事件
	mindMapInstance.value.on('node_tree_render_end', () => {
		// 使用 requestAnimationFrame 确保在浏览器下次重绘前执行，而不是使用不可靠的 setTimeout
		requestAnimationFrame(() => {
			if (!mindMapInstance.value) return;
			console.log('节点树渲染完毕事件');

			// 首次渲染时执行初始化操作
			if (isFirstRender.value) {
				// 居中显示
				try {
					// fit() 方法需要 3 个参数，但运行时可以不传参数使用默认值
					(mindMapInstance.value.view.fit as () => void)();
				} catch (error) {
					console.error('居中显示失败:', error);
				}

				// 标记首次渲染完成
				isFirstRender.value = false;
			}

			// 如果有待应用的高亮节点，在渲染完成后应用
			if (pendingHighlightNodes.value) {
				const { nodeIds, centerType, targetNodeId } = pendingHighlightNodes.value;
				pendingHighlightNodes.value = null;
				// 延迟一点确保 DOM 完全更新
				setTimeout(() => {
					applyHighlight(nodeIds);
					// 应用居中操作
					applyCenter(centerType, targetNodeId);
				}, 0);
			}

			// 如果有待执行的居中操作，在渲染完成后执行
			if (pendingFitToCenter.value) {
				pendingFitToCenter.value = false;
				setTimeout(() => {
					fitToCenter();
				}, 0);
			}

			// 2. 根据颜色模式应用样式
			if (props.colorMode === 'type') {
				applyNodeTypeStyles();
			}

			// 3. 应用多段渐变效果
			applyMultiGradients();

			// 4. 为所有节点绑定鼠标悬停事件
			bindNodeHoverEvents();
		});
	});

	// 画布的单击事件
	mindMapInstance.value.on('draw_click', () => {
		// 如果是节点点击触发的冒泡事件，则忽略
		if (isNodeClicked) {
			return;
		}

		// 只有在真正的点击（非拖动）时才清除高亮
		// 如果 hasMoved 为 true，说明是拖动操作，不执行 clearHighlight
		if (!mouseDownInfo.value.hasMoved) {
			clearHighlight();
		}

		// 无论点击还是拖动，都要隐藏右键菜单
		hideContextMenu();

		// 重置状态
		mouseDownInfo.value = {
			isDown: false,
			startX: 0,
			startY: 0,
			hasMoved: false
		};
	});

	// 使用库内置API监听鼠标事件，用于区分点击和拖动
	// 鼠标按下事件
	mindMapInstance.value.on('mousedown', (e: MouseEvent) => {
		mouseDownInfo.value = {
			isDown: true,
			startX: e.clientX,
			startY: e.clientY,
			hasMoved: false
		};
	});

	// 鼠标移动事件
	mindMapInstance.value.on('mousemove', (e: MouseEvent) => {
		if (!mouseDownInfo.value.isDown) return;

		// 计算移动距离
		const deltaX = Math.abs(e.clientX - mouseDownInfo.value.startX);
		const deltaY = Math.abs(e.clientY - mouseDownInfo.value.startY);
		const moveDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

		// 如果移动距离超过阈值（5px），认为是拖动
		if (moveDistance > 5) {
			mouseDownInfo.value.hasMoved = true;
		}
	});

	// 鼠标抬起事件
	mindMapInstance.value.on('mouseup', () => {
		// 延迟重置，确保 draw_click 事件能读取到状态
		setTimeout(() => {
			if (mouseDownInfo.value.isDown) {
				mouseDownInfo.value.isDown = false;
			}
		}, 100);
	});

	// 监听画布缩放事件
	mindMapInstance.value.on('scale', (scale: number) => {
		// 同步缩放值到 zoomValue（如果不是正在通过程序设置缩放）
		if (!isApplyingZoom.value) {
			const newZoomValue = scaleToZoomValue(scale);

			// 避免循环更新，只有当变化超过 0.1% 时才更新
			if (Math.abs(newZoomValue - internalZoomValue.value) > 0.1) {
				internalZoomValue.value = newZoomValue;
				emit('update:zoomValue', newZoomValue);
			}
		}
	});
};

// 性能优化：节点缓存（基于完整数据构建，存储节点ID信息）
const nodeCache = ref<{
	allNodeIds: string[]; // 所有节点ID列表
	nodeMap: Map<string, TreeNodeDataType>; // 节点ID -> 节点对象（用于存储，暂不使用）
	nameMap: Map<string, string[]>; // 节点名称 -> 节点ID数组
	typeMap: Map<string, string[]>; // 节点类型 -> 节点ID数组
	parentMap: Map<string, string>; // 子节点ID -> 父节点ID
	childrenMap: Map<string, string[]>; // 父节点ID -> 子节点ID数组
	nodeLevelMap: Map<string, number>; // 节点ID -> 层级（从0开始）
}>({
	allNodeIds: [],
	nodeMap: new Map(),
	nameMap: new Map(),
	typeMap: new Map(),
	parentMap: new Map(),
	childrenMap: new Map(),
	nodeLevelMap: new Map()
});
// 性能优化：构建节点缓存（基于完整数据）
const buildNodeCache = () => {
	if (!internalTreeData.value) return nodeCache.value;

	clearNodeCache();
	const allNodeIds: string[] = [];
	const nodeMap = new Map<string, TreeNodeDataType>();
	const nameMap = new Map<string, string[]>();
	const typeMap = new Map<string, string[]>();

	// 使用 convertToMindMapData 中已构建的映射
	const parentMap = relationMaps.value.parentMap;
	const childrenMap = relationMaps.value.childrenMap;
	const nodeLevelMap = relationMaps.value.nodeLevelMap || new Map<string, number>();

	// 递归遍历完整树数据，构建缓存
	const traverseTree = (node: TreeNodeDataType) => {
		const nodeId = node.data.uid || node.data.id;
		if (!nodeId) return;

		// 添加到所有节点ID列表
		allNodeIds.push(nodeId);
		// 存储节点对象
		nodeMap.set(nodeId, node);

		// 构建名称映射
		const nodeName = node.data.text || '';
		if (nodeName) {
			if (!nameMap.has(nodeName)) {
				nameMap.set(nodeName, []);
			}
			nameMap.get(nodeName)!.push(nodeId);
		}

		// 构建类型映射
		const nodeType = node.data.type || '';
		if (nodeType) {
			if (!typeMap.has(nodeType)) {
				typeMap.set(nodeType, []);
			}
			typeMap.get(nodeType)!.push(nodeId);
		}

		// 递归处理子节点
		if (node.children && node.children.length > 0) {
			node.children.forEach((child) => {
				traverseTree(child);
			});
		}
	};

	traverseTree(internalTreeData.value);

	nodeCache.value = {
		allNodeIds,
		nodeMap,
		nameMap,
		typeMap,
		parentMap,
		childrenMap,
		nodeLevelMap
	};
	return nodeCache.value;
};

// 清空节点缓存
const clearNodeCache = () => {
	nodeCache.value = {
		allNodeIds: [],
		nodeMap: new Map(),
		nameMap: new Map(),
		typeMap: new Map(),
		parentMap: new Map(),
		childrenMap: new Map(),
		nodeLevelMap: new Map()
	};
};

const globalEventHandlers = ref<
	{
		element: HTMLElement | Document;
		event: string;
		handler: (e: Event) => void;
	}[]
>([]);
// 添加全局事件监听器
const addGlobalEventListeners = () => {
	// 全局点击事件：点击空白处隐藏右键菜单
	const globalClickHandler = (e: Event) => {
		// 检查点击是否在右键菜单内部
		const contextMenu = contextMenuRef.value;
		if (contextMenu && contextMenu.contains(e.target as Node)) {
			return; // 点击在菜单内部，不隐藏
		}

		// 检查点击是否在思维导图容器内部
		const mindMapContainer = mindMapContainerRef.value;
		if (mindMapContainer && mindMapContainer.contains(e.target as Node)) {
			return; // 点击在思维导图内部，由其他事件处理
		}

		// 点击在外部，隐藏菜单
		hideContextMenu();
	};

	// 添加事件监听器
	document.addEventListener('click', globalClickHandler, true);

	// 保存处理器引用以便清理
	globalEventHandlers.value.push({
		element: document,
		event: 'click',
		handler: globalClickHandler
	});
};

// 清理全局事件监听器
const cleanupGlobalEventListeners = () => {
	globalEventHandlers.value.forEach(({ element, event, handler }) => {
		element.removeEventListener(event, handler, true);
	});
	globalEventHandlers.value = [];
};

// 存储事件处理器的引用，以便后续清理
const keyboardEventHandlers = ref<
	{
		element: HTMLElement | Document;
		event: string;
		handler: (e: Event) => void;
	}[]
>([]);
// 彻底禁用所有键盘快捷键
const disableAllKeyboardShortcuts = () => {
	if (!mindMapInstance.value) return;

	try {
		// 方法1: 尝试禁用keyCommand（如果存在的话）
		if (mindMapInstance.value.keyCommand) {
			const keyCommand = mindMapInstance.value.keyCommand as { disable?: () => void };
			if (typeof keyCommand.disable === 'function') {
				keyCommand.disable();
			}
		} else if (mindMapInstance.value.command) {
			const command = mindMapInstance.value.command as { disableShortcuts?: () => void };
			if (typeof command.disableShortcuts === 'function') {
				command.disableShortcuts();
			}
		}

		// 全局键盘事件处理器
		const globalKeyHandler = (e: KeyboardEvent) => {
			if (isInMindMapArea()) {
				preventKeyboard(e);
			}
		};

		// 容器键盘事件处理器
		const containerKeyHandler = (e: KeyboardEvent) => {
			preventKeyboard(e);
		};

		// 在思维导图容器上添加键盘事件拦截
		const container = mindMapContainerRef.value;
		if (container) {
			container.addEventListener('keydown', containerKeyHandler, true);
			container.addEventListener('keyup', containerKeyHandler, true);
			container.addEventListener('keypress', containerKeyHandler, true);

			// 确保容器可以接收键盘事件
			container.tabIndex = -1;

			// 保存处理器引用（转换为 (e: Event) => void 类型以匹配 removeEventListener）
			keyboardEventHandlers.value.push(
				{
					element: container,
					event: 'keydown',
					handler: containerKeyHandler as (e: Event) => void
				},
				{
					element: container,
					event: 'keyup',
					handler: containerKeyHandler as (e: Event) => void
				},
				{
					element: container,
					event: 'keypress',
					handler: containerKeyHandler as (e: Event) => void
				}
			);
		}

		// 在document级别添加全局拦截
		document.addEventListener('keydown', globalKeyHandler, true);
		document.addEventListener('keyup', globalKeyHandler, true);

		// 保存全局处理器引用（转换为 (e: Event) => void 类型以匹配 removeEventListener）
		keyboardEventHandlers.value.push(
			{ element: document, event: 'keydown', handler: globalKeyHandler as (e: Event) => void },
			{ element: document, event: 'keyup', handler: globalKeyHandler as (e: Event) => void }
		);
	} catch (error) {
		console.error('禁用键盘快捷键时出错:', error);
	}
};

// 清理键盘事件监听器
const cleanupKeyboardEventListeners = () => {
	keyboardEventHandlers.value.forEach(({ element, event, handler }) => {
		element.removeEventListener(event, handler, true);
	});
	keyboardEventHandlers.value = [];
};

// 通用的键盘事件阻止函数
const preventKeyboard = (e: KeyboardEvent) => {
	// 更全面的快捷键列表
	const isShortcut =
		e.key === 'Delete' ||
		e.key === 'Backspace' ||
		e.key === 'Tab' ||
		e.key === 'Enter' ||
		e.key === 'Escape' ||
		e.key === 'F2' ||
		e.key === 'Insert' ||
		(e.ctrlKey && (e.key === 'c' || e.key === 'C')) ||
		(e.ctrlKey && (e.key === 'v' || e.key === 'V')) ||
		(e.ctrlKey && (e.key === 'x' || e.key === 'X')) ||
		(e.ctrlKey && (e.key === 'z' || e.key === 'Z')) ||
		(e.ctrlKey && (e.key === 'y' || e.key === 'Y')) ||
		(e.ctrlKey && (e.key === 'a' || e.key === 'A')) ||
		(e.ctrlKey && (e.key === 'd' || e.key === 'D')) ||
		(e.ctrlKey && (e.key === 's' || e.key === 'S')) ||
		(e.ctrlKey && e.shiftKey && (e.key === 'z' || e.key === 'Z')) ||
		(e.altKey && e.key === 'F4') ||
		// 方向键组合
		(e.ctrlKey && ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) ||
		(e.shiftKey && ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) ||
		// F功能键
		['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'].includes(e.key) ||
		// 其他常见快捷键
		(e.key === ' ' && e.ctrlKey) || // Ctrl+Space
		e.key === 'Home' ||
		e.key === 'End' ||
		e.key === 'PageUp' ||
		e.key === 'PageDown';

	if (isShortcut) {
		e.preventDefault();
		e.stopPropagation();
		e.stopImmediatePropagation();
		return false;
	}
};

// 彻底禁用节点编辑功能
const disableNodeEditing = () => {
	if (!mindMapInstance.value) return;

	try {
		// 方法1: 直接禁用textEdit实例
		if (mindMapInstance.value.renderer && mindMapInstance.value.renderer.textEdit) {
			const textEdit = mindMapInstance.value.renderer.textEdit;

			// 重写showEditTextBox方法使其无效
			textEdit.showEditTextBox = () => {
				return false;
			};

			// 重写show方法使其无效
			textEdit.show = () => {
				return Promise.reject();
			};

			// 确保编辑框始终隐藏
			textEdit.hideEditTextBox && textEdit.hideEditTextBox();
		}

		// 方法2: 禁用相关配置
		if (mindMapInstance.value.opt) {
			mindMapInstance.value.opt.enableNodeTextEditOnDoubleClick = false;
		}

		// 方法3: 拦截所有可能的编辑触发方式
		const originalExecCommand = mindMapInstance.value.execCommand;
		mindMapInstance.value.execCommand = function (name: string, ...args: unknown[]) {
			// 阻止文本编辑相关的命令
			if (name === 'TEXT_EDIT' || name === 'START_TEXT_EDIT' || name === 'EDIT_NODE_TEXT') {
				return false;
			}
			// 其他命令正常执行
			return originalExecCommand.call(this, name, ...args);
		};
	} catch (error) {
		console.error('禁用节点编辑时出错:', error);
	}
};

/** -------------------节点信息气泡框------------------- */
// 气泡框相关数据
const nodeTooltipRef = ref<HTMLElement | null>(null);
const tooltipVisible = ref(false);
const tooltipStyle = ref<{ left?: string; top?: string; transform?: string }>({});
const tooltipData = ref<{ name: string; type: string }>({ name: '', type: '' });

// 显示节点信息气泡框
const showNodeTooltip = (nodeElement: HTMLElement, name: string, type: string) => {
	// 清除之前的隐藏定时器
	if (tooltipHideTimer) {
		clearTimeout(tooltipHideTimer);
		tooltipHideTimer = null;
	}

	// 使用 typeMap 将类型转换为中文
	const typeLabel = props.typeMap?.get(type) || type;
	tooltipData.value = { name, type: typeLabel };

	// 获取节点元素的位置信息
	const nodeRect = nodeElement.getBoundingClientRect();
	// 计算节点顶部中心位置
	const nodeCenterX = nodeRect.left + nodeRect.width / 2;
	const nodeTopY = nodeRect.top;

	const offset = 10; // 距离节点顶部的偏移量

	// 计算 tooltip 位置：节点顶部中心位置上方
	// 使用 transform: translate(-50%, -100%) 实现居中和向上偏移
	tooltipStyle.value = {
		left: `${nodeCenterX}px`,
		top: `${nodeTopY - offset}px`,
		transform: 'translate(-50%, -100%)' // 水平居中，垂直向上偏移100%
	};

	tooltipVisible.value = true;
};

// tooltip 隐藏延迟定时器
let tooltipHideTimer: ReturnType<typeof setTimeout> | null = null;

// 隐藏节点信息气泡框（带延迟，避免快速移动时闪烁）
const hideNodeTooltip = () => {
	if (tooltipHideTimer) {
		clearTimeout(tooltipHideTimer);
	}
	tooltipHideTimer = setTimeout(() => {
		tooltipVisible.value = false;
		tooltipHideTimer = null;
	}, 100); // 100ms 延迟，避免快速移动时闪烁
};

// 存储节点事件监听器的映射，用于清理
const nodeEventListeners = ref<
	Map<HTMLElement, { mouseenter: (e: MouseEvent) => void; mouseleave: () => void }>
>(new Map());

// 为所有节点绑定鼠标悬停事件
const bindNodeHoverEvents = () => {
	if (!mindMapInstance.value || !mindMapContainerRef.value) return;

	// 先清理之前的事件监听器
	cleanupNodeHoverEvents();

	const container = mindMapContainerRef.value;
	// 查找所有节点元素
	const nodeElements = container.querySelectorAll('.smm-node');

	// 获取所有节点实例的映射（通过遍历树结构）
	const root = mindMapInstance.value.renderer?.root;
	if (!root) return;

	const allNodes = getAllNodes(root);
	// 创建节点元素到节点实例的映射
	const nodeElementToInstanceMap = new Map<HTMLElement, TreeNodeElType>();

	allNodes.forEach((nodeInstance) => {
		const nodeEl = nodeInstance.group?.node as HTMLElement;
		if (nodeEl) {
			nodeElementToInstanceMap.set(nodeEl, nodeInstance);
		}
	});

	nodeElements.forEach((nodeElement) => {
		const htmlElement = nodeElement as HTMLElement;

		// 查找对应的节点实例
		let targetNodeInstance: TreeNodeElType | undefined;

		// 方法1: 直接匹配
		targetNodeInstance = nodeElementToInstanceMap.get(htmlElement);

		// 方法2: 如果直接匹配失败，尝试查找包含该元素的节点
		if (!targetNodeInstance) {
			for (const [nodeEl, instance] of nodeElementToInstanceMap.entries()) {
				if (nodeEl.contains(htmlElement) || htmlElement.contains(nodeEl)) {
					targetNodeInstance = instance;
					break;
				}
			}
		}

		if (!targetNodeInstance || !targetNodeInstance.nodeData?.data) return;

		// 鼠标进入事件处理
		const mouseenterHandler = () => {
			try {
				const nodeData = targetNodeInstance!.nodeData!.data;
				const nodeName = (nodeData.text as string) || '';
				const nodeType = (nodeData.type as string) || '';

				// 获取实际的节点元素（优先使用 nodeInstance.group.node，否则使用 htmlElement）
				const actualNodeElement = (targetNodeInstance!.group?.node as HTMLElement) || htmlElement;
				showNodeTooltip(actualNodeElement, nodeName, nodeType);
			} catch (error) {
				console.debug('显示节点信息失败:', error);
			}
		};

		// 鼠标离开事件处理
		const mouseleaveHandler = () => {
			hideNodeTooltip();
		};

		// 绑定事件
		htmlElement.addEventListener('mouseenter', mouseenterHandler);
		htmlElement.addEventListener('mouseleave', mouseleaveHandler);

		// 保存事件监听器引用以便清理
		nodeEventListeners.value.set(htmlElement, {
			mouseenter: mouseenterHandler,
			mouseleave: mouseleaveHandler
		});
	});
};

// 清理节点悬停事件监听器
const cleanupNodeHoverEvents = () => {
	nodeEventListeners.value.forEach((handlers, element) => {
		element.removeEventListener('mouseenter', handlers.mouseenter);
		element.removeEventListener('mouseleave', handlers.mouseleave);
	});
	nodeEventListeners.value.clear();

	// 清除 tooltip 隐藏定时器
	if (tooltipHideTimer) {
		clearTimeout(tooltipHideTimer);
		tooltipHideTimer = null;
	}

	// 隐藏 tooltip
	tooltipVisible.value = false;
};

/** -------------------右键菜单------------------- */
// 右键菜单相关数据
const contextMenuVisible = ref(false);
const contextMenuStyle = ref<{ left?: string; top?: string }>({});
const currentRightClickNode = ref<MindMapNodeEvent | null>(null);
// 显示右键菜单
const showContextMenu = (x: number, y: number, node: MindMapNodeEvent) => {
	if (!node) {
		console.warn('无法显示菜单：节点为空');
		return;
	}

	currentRightClickNode.value = node;

	// 计算菜单位置
	const menuPosition = calculateMenuPosition(x, y);

	contextMenuStyle.value = {
		left: `${menuPosition.x}px`,
		top: `${menuPosition.y}px`
	};

	contextMenuVisible.value = true;
};

// 隐藏右键菜单
const hideContextMenu = () => {
	contextMenuVisible.value = false;
	currentRightClickNode.value = null;
};

// 计算菜单位置，确保菜单不会超出视窗边界
const calculateMenuPosition = (x: number, y: number) => {
	const menuWidth = 180; // 菜单宽度
	const menuHeight = 200; // 菜单高度（大致估算）

	const viewportWidth = window.innerWidth;
	const viewportHeight = window.innerHeight;

	let adjustedX = x;
	let adjustedY = y;

	// 检查右边界
	if (x + menuWidth > viewportWidth) {
		adjustedX = viewportWidth - menuWidth - 10;
	}

	// 检查左边界
	if (adjustedX < 10) {
		adjustedX = 10;
	}

	// 检查下边界
	if (y + menuHeight > viewportHeight) {
		adjustedY = viewportHeight - menuHeight - 10;
	}

	// 检查上边界
	if (adjustedY < 10) {
		adjustedY = 10;
	}

	return { x: adjustedX, y: adjustedY };
};

// 插入同级节点
const insertSiblingNode = () => {
	if (!currentRightClickNode.value) {
		console.warn('无法插入同级节点：当前节点为空');
		return;
	}

	try {
		const currentNode = currentRightClickNode.value;

		// 获取当前节点的父节点（同级节点的父节点）
		const parentNode = currentNode.parent;
		if (!parentNode) {
			console.warn('无法插入同级节点：当前节点没有父节点');
			emit('node-context-menu-action', {
				action: 'insertSiblingNode',
				nodeId: currentNode.uid,
				nodeText: (currentNode.nodeData?.data?.text as string) || '',
				warning: '当前节点没有父节点，无法插入同级节点',
				timestamp: new Date().toISOString()
			});
			return;
		}

		if (mindMapInstance.value) {
			// 激活当前节点
			mindMapInstance.value.renderer.activeNodeList = [currentNode];

			// 使用 INSERT_NODE 命令插入同级节点
			mindMapInstance.value.execCommand('INSERT_NODE', false);
		}

		// 发送emit事件通知父组件，传递父节点信息
		emit('node-context-menu-action', {
			action: 'insertSiblingNode',
			currentNodeId: currentNode.uid,
			currentNodeText: (currentNode.nodeData?.data?.text as string) || '',
			parentNodeId: parentNode.uid,
			parentNodeText: (parentNode.nodeData?.data?.text as string) || '',
			parentNodeType: (parentNode.nodeData?.data?.type as string) || '',
			timestamp: new Date().toISOString()
		});
	} catch (error) {
		console.error('插入同级节点时出错:', error);
		// 发送错误事件
		emit('node-context-menu-action', {
			action: 'insertSiblingNode',
			nodeId: (currentRightClickNode.value?.uid as string) || '',
			error: (error as Error)?.message || '',
			timestamp: new Date().toISOString()
		});
	} finally {
		hideContextMenu();
	}
};

// 插入子级节点
const insertChildNode = () => {
	if (!currentRightClickNode.value) {
		console.warn('无法插入子级节点：当前节点为空');
		return;
	}

	try {
		const currentNode = currentRightClickNode.value;

		// 激活当前节点
		if (mindMapInstance.value) {
			mindMapInstance.value.renderer.activeNodeList = [currentNode];

			// 使用 INSERT_CHILD_NODE 命令插入子级节点
			mindMapInstance.value.execCommand('INSERT_CHILD_NODE', false);
		}

		// 发送emit事件通知父组件，传递父节点（当前激活节点）信息
		emit('node-context-menu-action', {
			action: 'insertChildNode',
			parentNodeId: currentNode.uid,
			parentNodeText: (currentNode.nodeData?.data?.text as string) || '',
			parentNodeType: (currentNode.nodeData?.data?.type as string) || '',
			timestamp: new Date().toISOString()
		});
	} catch (error) {
		console.error('插入子级节点时出错:', error);
		// 发送错误事件
		emit('node-context-menu-action', {
			action: 'insertChildNode',
			nodeId: (currentRightClickNode.value?.uid as string) || '',
			error: (error as Error)?.message || '',
			timestamp: new Date().toISOString()
		});
	} finally {
		hideContextMenu();
	}
};

// 插入父级节点
const insertParentNode = () => {
	if (!currentRightClickNode.value) {
		console.warn('无法插入父级节点：当前节点为空');
		return;
	}

	try {
		const currentNode = currentRightClickNode.value;

		// 获取当前节点的父节点（新插入父节点的父节点）
		const grandParentNode = currentNode.parent;
		if (!grandParentNode) {
			console.warn('无法插入父级节点：当前节点没有父节点');
			emit('node-context-menu-action', {
				action: 'insertParentNode',
				nodeId: currentNode.uid,
				nodeText: (currentNode.nodeData?.data?.text as string) || '',
				warning: '当前节点没有父节点，无法插入父级节点',
				timestamp: new Date().toISOString()
			});
			return;
		}

		// 激活当前节点
		if (mindMapInstance.value) {
			mindMapInstance.value.renderer.activeNodeList = [currentNode];

			// 使用 INSERT_PARENT_NODE 命令插入父级节点
			mindMapInstance.value.execCommand('INSERT_PARENT_NODE', false);
		}

		// 发送emit事件通知父组件，传递当前节点和新插入父节点的父节点信息
		emit('node-context-menu-action', {
			action: 'insertParentNode',
			currentNodeId: currentNode.uid,
			currentNodeText: (currentNode.nodeData?.data?.text as string) || '',
			currentNodeType: (currentNode.nodeData?.data?.type as string) || '',
			grandParentNodeId: grandParentNode.uid,
			grandParentNodeText: (grandParentNode.nodeData?.data?.text as string) || '',
			grandParentNodeType: (grandParentNode.nodeData?.data?.type as string) || '',
			timestamp: new Date().toISOString()
		});
	} catch (error) {
		console.error('插入父级节点时出错:', error);
		// 发送错误事件
		emit('node-context-menu-action', {
			action: 'insertParentNode',
			nodeId: (currentRightClickNode.value?.uid as string) || '',
			error: (error as Error)?.message || '',
			timestamp: new Date().toISOString()
		});
	} finally {
		hideContextMenu();
	}
};

// 删除节点（包含子节点）
const deleteNodeWithChildren = () => {
	if (!currentRightClickNode.value) {
		console.warn('无法删除节点：当前节点为空');
		return;
	}

	try {
		const currentNode = currentRightClickNode.value;

		// 检查是否为根节点
		if (currentNode.isRoot) {
			console.warn('无法删除根节点');
			// 发送根节点删除限制事件
			emit('node-context-menu-action', {
				action: 'deleteNodeWithChildren',
				nodeId: currentNode.uid,
				nodeText: (currentNode.nodeData?.data?.text as string) || '',
				warning: '无法删除根节点',
				timestamp: new Date().toISOString()
			});
			return;
		}

		// 激活当前节点
		if (mindMapInstance.value) {
			mindMapInstance.value.renderer.activeNodeList = [currentNode];

			// 使用 REMOVE_NODE 命令删除节点及其子节点
			mindMapInstance.value.execCommand('REMOVE_NODE');
		}

		// 发送emit事件通知父组件
		emit('node-context-menu-action', {
			action: 'deleteNodeWithChildren',
			nodeId: currentNode.uid,
			nodeText: (currentNode.nodeData?.data?.text as string) || '',
			timestamp: new Date().toISOString()
		});
	} catch (error) {
		console.error('删除节点时出错:', error);
		// 发送错误事件
		emit('node-context-menu-action', {
			action: 'deleteNodeWithChildren',
			nodeId: (currentRightClickNode.value?.uid as string) || '',
			error: (error as Error)?.message || '',
			timestamp: new Date().toISOString()
		});
	} finally {
		hideContextMenu();
	}
};

// 仅删除当前节点（保留子节点）
const deleteCurrentNodeOnly = () => {
	if (!currentRightClickNode.value) {
		console.warn('无法删除当前节点：当前节点为空');
		return;
	}

	try {
		const currentNode = currentRightClickNode.value;

		// 检查是否为根节点
		if (currentNode.isRoot) {
			console.warn('无法删除根节点');
			// 发送根节点删除限制事件
			emit('node-context-menu-action', {
				action: 'deleteCurrentNodeOnly',
				nodeId: currentNode.uid,
				nodeText: (currentNode.nodeData?.data?.text as string) || '',
				warning: '无法删除根节点',
				timestamp: new Date().toISOString()
			});
			return;
		}

		// 激活当前节点
		if (mindMapInstance.value) {
			mindMapInstance.value.renderer.activeNodeList = [currentNode];

			// 使用 REMOVE_CURRENT_NODE 命令仅删除当前节点
			mindMapInstance.value.execCommand('REMOVE_CURRENT_NODE');
		}

		// 发送emit事件通知父组件
		emit('node-context-menu-action', {
			action: 'deleteCurrentNodeOnly',
			nodeId: currentNode.uid,
			nodeText: (currentNode.nodeData?.data?.text as string) || '',
			timestamp: new Date().toISOString()
		});
	} catch (error) {
		console.error('删除当前节点时出错:', error);
		// 发送错误事件
		emit('node-context-menu-action', {
			action: 'deleteCurrentNodeOnly',
			nodeId: (currentRightClickNode.value?.uid as string) || '',
			error: (error as Error)?.message || '',
			timestamp: new Date().toISOString()
		});
	} finally {
		hideContextMenu();
	}
};

/** -------------------API方法------------------- */
// API1 方法：按照节点id高亮指定节点 (支持字符串或数组)
// 参数：targetNodeIds - 目标节点ID（字符串或数组）
// 参数：enableChange - 是否启用布局调整，默认为 true
const highlightNodeByNodeId = (targetNodeIds: string | string[], enableChange = true) => {
	if (!mindMapInstance.value) return;

	// 清除之前的高亮
	clearHighlight();

	try {
		const result = findNodesByCondition({ type: 'id', value: targetNodeIds }, false);

		if (result.highlightNodeIds.size === 0) {
			console.warn('未找到目标节点:', targetNodeIds);
			return;
		}

		// 判断是单个节点还是多个节点
		const isSingleNode = result.highlightNodeIds.size === 1;
		const targetNodeId = isSingleNode ? Array.from(result.highlightNodeIds)[0] : undefined;

		// 展开相关的收起节点（高亮会在展开完成后自动应用）
		expandRelatedNodes(
			result.highlightNodeIds,
			isSingleNode ? 'single' : 'multiple',
			targetNodeId,
			enableChange
		);
	} catch (error) {
		console.error('按节点ID高亮时出错:', error);
	}
};

// API2 方法：按照节点id高亮指定节点及其子节点(支持字符串或数组)
// 参数：targetNodeIds - 目标节点ID（字符串或数组）
// 参数：enableChange - 是否启用布局调整，默认为 true
const highlightNodeAndChildrenByNodeId = (
	targetNodeIds: string | string[],
	enableChange = true
) => {
	if (!mindMapInstance.value) return;

	// 清除之前的高亮
	clearHighlight();

	try {
		const result = findNodesByCondition({ type: 'id', value: targetNodeIds }, true);

		if (result.highlightNodeIds.size === 0) {
			console.warn('未找到目标节点:', targetNodeIds);
			return;
		}

		// 判断是单个节点还是多个节点
		const isSingleNode = result.highlightNodeIds.size === 1;
		const targetNodeId = isSingleNode ? Array.from(result.highlightNodeIds)[0] : undefined;

		// 展开相关的收起节点（高亮会在展开完成后自动应用）
		expandRelatedNodes(
			result.highlightNodeIds,
			isSingleNode ? 'single' : 'multiple',
			targetNodeId,
			enableChange
		);
	} catch (error) {
		console.error('按节点ID高亮节点及其子节点时出错:', error);
	}
};

// API3 方法：按照节点名称高亮指定节点 (支持字符串或数组)
// 参数：targetNodeNames - 目标节点名称（字符串或数组）
// 参数：enableChange - 是否启用布局调整，默认为 true
const highlightNodeByNodeName = (targetNodeNames: string | string[], enableChange = true) => {
	if (!mindMapInstance.value) return;

	// 清除之前的高亮
	clearHighlight();

	try {
		const result = findNodesByCondition({ type: 'name', value: targetNodeNames }, false);

		if (result.highlightNodeIds.size === 0) {
			console.warn('未找到目标节点:', targetNodeNames);
			return;
		}

		// 判断是单个节点还是多个节点
		const isSingleNode = result.highlightNodeIds.size === 1;
		const targetNodeId = isSingleNode ? Array.from(result.highlightNodeIds)[0] : undefined;

		// 展开相关的收起节点（高亮会在展开完成后自动应用）
		expandRelatedNodes(
			result.highlightNodeIds,
			isSingleNode ? 'single' : 'multiple',
			targetNodeId,
			enableChange
		);
	} catch (error) {
		console.error('按节点名称高亮时出错:', error);
	}
};

// API4 方法：按照节点名称高亮指定节点及其子节点 (支持字符串或数组)
// 参数：targetNodeNames - 目标节点名称（字符串或数组）
// 参数：enableChange - 是否启用布局调整，默认为 true
const highlightNodeAndChildrenByNodeName = (
	targetNodeNames: string | string[],
	enableChange = true
) => {
	if (!mindMapInstance.value) return;

	// 清除之前的高亮
	clearHighlight();

	try {
		const result = findNodesByCondition({ type: 'name', value: targetNodeNames }, true);

		if (result.highlightNodeIds.size === 0) {
			console.warn('未找到目标节点:', targetNodeNames);
			return;
		}

		// 判断是单个节点还是多个节点
		const isSingleNode = result.highlightNodeIds.size === 1;
		const targetNodeId = isSingleNode ? Array.from(result.highlightNodeIds)[0] : undefined;

		// 展开相关的收起节点（高亮会在展开完成后自动应用）
		expandRelatedNodes(
			result.highlightNodeIds,
			isSingleNode ? 'single' : 'multiple',
			targetNodeId,
			enableChange
		);
	} catch (error) {
		console.error('按节点名称高亮节点及其子节点时出错:', error);
	}
};

// API5 方法：按类型高亮节点(支持字符串或数组)
// 参数：targetType - 目标节点类型（字符串或数组）
// 参数：enableChange - 是否启用布局调整，默认为 true
const highlightNodeByType = (targetType: string | string[], enableChange = true) => {
	if (!targetType || !mindMapInstance.value) return;

	// 清除之前的高亮
	clearHighlight();

	try {
		const result = findNodesByCondition({ type: 'type', value: targetType }, false);

		if (result.highlightNodeIds.size === 0) {
			console.warn('未找到目标类型的节点:', targetType);
			return;
		}

		// 判断是单个节点还是多个节点
		const isSingleNode = result.highlightNodeIds.size === 1;
		const targetNodeId = isSingleNode ? Array.from(result.highlightNodeIds)[0] : undefined;

		// 展开相关的收起节点（高亮会在展开完成后自动应用）
		expandRelatedNodes(
			result.highlightNodeIds,
			isSingleNode ? 'single' : 'multiple',
			targetNodeId,
			enableChange
		);
	} catch (error) {
		console.error('按类型高亮时出错:', error);
	}
};

// API6 方法：按类型高亮节点及其子节点（支持字符串或数组）
// 参数：targetType - 目标节点类型（字符串或数组）
// 参数：enableChange - 是否启用布局调整，默认为 true
const highlightNodeAndChildrenByType = (targetType: string | string[], enableChange = true) => {
	if (!targetType || !mindMapInstance.value) return;

	// 清除之前的高亮
	clearHighlight();

	try {
		const result = findNodesByCondition({ type: 'type', value: targetType }, true);

		if (result.highlightNodeIds.size === 0) {
			console.warn('未找到目标类型的节点:', targetType);
			return;
		}

		// 判断是单个节点还是多个节点
		const isSingleNode = result.highlightNodeIds.size === 1;
		const targetNodeId = isSingleNode ? Array.from(result.highlightNodeIds)[0] : undefined;

		// 展开相关的收起节点（高亮会在展开完成后自动应用）
		expandRelatedNodes(
			result.highlightNodeIds,
			isSingleNode ? 'single' : 'multiple',
			targetNodeId,
			enableChange
		);
	} catch (error) {
		console.error('按类型高亮节点及其子节点时出错:', error);
	}
};

// API7 方法：清除高亮效果
const clearHighlight = () => {
	if (!mindMapInstance.value) return;

	try {
		const cache = nodeCache.value;
		// 使用库的API根据nodeId获取节点实例
		cache.allNodeIds.forEach((nodeId) => {
			try {
				const nodeInstance = mindMapInstance.value?.renderer.findNodeByUid(nodeId);
				if (nodeInstance && nodeInstance.group?.node) {
					const nodeElement = nodeInstance.group.node as HTMLElement;
					if (nodeElement) {
						// 清除CSS类
						nodeElement.classList.remove('node-highlighted');
						nodeElement.classList.remove('node-dimmed');

						// 清除内联样式
						clearNodeInlineStyles(nodeElement);

						// 清除自定义属性
						nodeElement.removeAttribute('data-highlight-state');
					}
				}
			} catch (error) {
				// 节点可能还未渲染（被收起），忽略错误
				console.debug('节点未渲染，跳过清除高亮:', nodeId, error);
			}
		});

		highlightedNodes.value.clear();
	} catch (error) {
		console.error('清除高亮时出错:', error);
	}
};

// API8 方法：按层级展示节点
const showByLevel = (level: string | number) => {
	if (!mindMapInstance.value) return;

	try {
		const root = mindMapInstance.value.renderer?.root;
		if (!root) {
			console.warn('根节点不可用');
			return;
		}

		// 设置标记，等待渲染完成后执行居中
		pendingFitToCenter.value = true;

		if (level === 'all') {
			// 全部展开
			mindMapInstance.value.command.exec('EXPAND_ALL');
			return;
		}

		const targetLevel = parseInt(String(level));
		if (isNaN(targetLevel)) {
			pendingFitToCenter.value = false;
			return;
		}

		// 展开到指定层级
		if (
			!nodeCache.value ||
			!nodeCache.value.nodeLevelMap ||
			nodeCache.value.nodeLevelMap.size === 0
		) {
			console.warn('节点层级信息未初始化，无法按层级展示');
			pendingFitToCenter.value = false;
			return;
		}

		// 收集所有层级 <= targetLevel 的节点 uid
		const nodesToExpand: string[] = [];
		nodeCache.value.nodeLevelMap.forEach((nodeLevel, nodeId) => {
			// 如果节点层级 <= targetLevel，则添加到展开列表
			if (nodeLevel <= targetLevel) {
				nodesToExpand.push(nodeId);
			}
		});

		// 对每个符合条件的节点调用 EXPAND_ALL
		nodesToExpand.forEach((uid) => {
			try {
				mindMapInstance.value?.execCommand('EXPAND_ALL', uid);
			} catch (error) {
				console.warn('展开节点失败:', uid, error);
			}
		});
	} catch (error) {
		console.error('按层级展示时出错:', error);
		pendingFitToCenter.value = false;
	}
};

// API9 方法：添加单个节点
const addNode = (nodeData: NodeDataForAdd, parentNodeId: string | null = null) => {
	try {
		if (!mindMapInstance.value) {
			console.error('添加节点失败: 思维导图实例未初始化');
			return false;
		}

		// 验证节点数据
		const nodeValidation = validateNodeData(nodeData);
		if (!nodeValidation.valid) {
			console.error('添加节点失败:', nodeValidation.error);
			return false;
		}

		if (parentNodeId) {
			// 查找父节点
			const parentNode = mindMapInstance.value.renderer.findNodeByUid(parentNodeId);
			if (!parentNode) {
				console.error('添加节点失败: 父节点不存在', parentNodeId);
				return false;
			}

			// 激活父节点
			mindMapInstance.value.renderer.activeNodeList = [parentNode];

			// 使用库原生API添加子节点
			mindMapInstance.value.execCommand('INSERT_CHILD_NODE', false, [], {
				uid: nodeData.id,
				text: nodeData.label,
				type: nodeData.type,
				data: {
					...nodeData // 支持其他自定义属性
				}
			});
		} else {
			// 如果没有指定父节点，添加为根节点的子节点
			const rootNode = mindMapInstance.value.renderer.root;
			if (rootNode) {
				mindMapInstance.value.renderer.activeNodeList = [rootNode];
				mindMapInstance.value.execCommand('INSERT_CHILD_NODE', false, [], {
					uid: nodeData.id,
					text: nodeData.label,
					type: nodeData.type,
					data: {
						...nodeData
					}
				});
			} else {
				console.error('添加节点失败: 无法找到根节点');
				return false;
			}
		}

		// 注意：样式会在 node_tree_render_end 事件中统一应用
		return true;
	} catch (error) {
		console.error('添加节点时出错:', error);
		return false;
	}
};

// API10 方法：批量添加节点
const addNodes = (nodesData: NodeDataForAddPatch[]) => {
	try {
		if (!mindMapInstance.value) {
			console.error('批量添加节点失败: 思维导图实例未初始化');
			return false;
		}

		if (!Array.isArray(nodesData)) {
			console.error('添加节点失败: nodesData必须是数组');
			return false;
		}

		if (nodesData.length === 0) {
			console.warn('没有节点需要添加');
			return true;
		}

		// 预先验证所有节点数据
		for (const nodeConfig of nodesData) {
			const { nodeData } = nodeConfig;
			const nodeValidation = validateNodeData(nodeData);
			if (!nodeValidation.valid) {
				console.error('批量添加节点失败:', nodeValidation.error, nodeData);
				return false;
			}
		}

		const failedNodes = [];

		// 逐个添加节点
		for (const nodeConfig of nodesData) {
			const { nodeData, parentNodeId = null } = nodeConfig;

			try {
				if (parentNodeId) {
					// 查找父节点
					const parentNode = mindMapInstance.value.renderer.findNodeByUid(parentNodeId);
					if (!parentNode) {
						console.error('跳过节点添加: 父节点不存在', parentNodeId, nodeData.id);
						failedNodes.push({ nodeData, reason: '父节点不存在' });
						continue;
					}

					// 激活父节点并添加子节点
					mindMapInstance.value.renderer.activeNodeList = [parentNode];
					mindMapInstance.value.execCommand('INSERT_CHILD_NODE', false, [], {
						uid: nodeData.id,
						text: nodeData.label,
						type: nodeData.type,
						data: {
							...nodeData
						}
					});
				} else {
					// 添加为根节点的子节点
					const rootNode = mindMapInstance.value.renderer.root;
					if (rootNode) {
						mindMapInstance.value.renderer.activeNodeList = [rootNode];
						mindMapInstance.value.execCommand('INSERT_CHILD_NODE', false, [], {
							uid: nodeData.id,
							text: nodeData.label,
							type: nodeData.type,
							data: {
								...nodeData
							}
						});
					} else {
						failedNodes.push({ nodeData, reason: '无法找到根节点' });
						continue;
					}
				}
			} catch (error) {
				console.error('添加单个节点失败:', error, nodeData.id);
				failedNodes.push({ nodeData, reason: (error as Error)?.message || '' });
			}
		}

		return failedNodes.length === 0;
	} catch (error) {
		console.error('批量添加节点时出错:', error);
		return false;
	}
};

// API11 方法：删除单个或多个节点
const removeNode = (nodeIds: string | string[], removeChildren = false) => {
	try {
		if (!mindMapInstance.value) {
			console.error('删除节点失败: 思维导图实例未初始化');
			return false;
		}

		// 统一处理单个ID或ID数组
		const targetNodeIds = Array.isArray(nodeIds) ? nodeIds : [nodeIds];

		if (targetNodeIds.length === 0 || targetNodeIds.some((id) => !id)) {
			console.error('删除节点失败: 节点ID不能为空');
			return false;
		}

		const nodesToDelete: TreeNodeElType[] = [];
		const failedNodes = [];

		// 查找所有要删除的节点
		targetNodeIds.forEach((nodeId: string) => {
			const node = mindMapInstance.value?.renderer.findNodeByUid(nodeId);
			if (node) {
				nodesToDelete.push(node);
			} else {
				failedNodes.push({ nodeId, reason: '节点不存在' });
			}
		});

		if (nodesToDelete.length === 0) {
			console.error('删除节点失败: 所有指定的节点都不存在');
			return false;
		}

		// 激活要删除的节点
		mindMapInstance.value.renderer.activeNodeList = nodesToDelete;

		// 使用库原生API删除节点
		if (removeChildren) {
			// 删除节点及其所有子节点
			mindMapInstance.value.execCommand('REMOVE_NODE');
		} else {
			// 只删除当前节点，保留子节点
			mindMapInstance.value.execCommand('REMOVE_CURRENT_NODE');
		}

		return failedNodes.length === 0;
	} catch (error) {
		console.error('删除节点时出错:', error);
		return false;
	}
};

// API12 方法：编辑单个节点
const editNode = (nodeId: string, updateData: UpdateNodeData) => {
	try {
		if (!mindMapInstance.value) {
			console.error('编辑节点失败: 思维导图实例未初始化');
			return false;
		}

		if (!nodeId) {
			console.error('编辑节点失败: 节点ID不能为空');
			return false;
		}

		if (!updateData || typeof updateData !== 'object') {
			console.error('编辑节点失败: 更新数据必须是一个对象');
			return false;
		}

		// 不允许修改节点ID
		if (Object.prototype.hasOwnProperty.call(updateData, 'id')) {
			console.error('编辑节点失败: 不允许修改节点ID');
			return false;
		}

		// 查找节点实例
		const targetNode = mindMapInstance.value.renderer.findNodeByUid(nodeId);
		if (!targetNode) {
			console.error('编辑节点失败: 节点不存在', nodeId);
			return false;
		}

		// 验证label字段
		if (Object.prototype.hasOwnProperty.call(updateData, 'label')) {
			if (!updateData.label || typeof updateData.label !== 'string') {
				console.error('编辑节点失败: label必须是非空字符串');
				return false;
			}
		}

		// 激活节点
		mindMapInstance.value.execCommand('SET_NODE_DATA', targetNode, {
			type: updateData.type,
			text: updateData.label
		});

		// 重新渲染节点
		(mindMapInstance.value.render as () => void)();
		// 注意：样式会在 node_tree_render_end 事件中统一应用

		return true;
	} catch (error) {
		console.error('编辑节点时出错:', error);
		return false;
	}
};

// API13 方法：获取当前数据
const getCurrentData = () => {
	return internalTreeData.value;
};

// API14 方法：思维导图实例访问
const getMindMapInstance = () => {
	return mindMapInstance.value;
};

// API15 方法：定位到中心
const fitToCenter = () => {
	if (!mindMapInstance.value) return;

	try {
		// 使用 fit() 方法居中显示整个思维导图
		(mindMapInstance.value.view.fit as () => void)();
	} catch (error) {
		console.error('定位到中心失败:', error);
	}
};

// 放大（增加缩放值）
const zoomIn = () => {
	const step = 10; // 每次增加 10%
	const newValue = Math.min(400, internalZoomValue.value + step);
	internalZoomValue.value = newValue;
	applyZoomFromValue(newValue);
};

// 缩小（减少缩放值）
const zoomOut = () => {
	const step = 10; // 每次减少 10%
	const newValue = Math.max(20, internalZoomValue.value - step);
	internalZoomValue.value = newValue;
	applyZoomFromValue(newValue);
};

// 设置缩放值
const setZoomValue = (value: number) => {
	const clampedValue = Math.max(20, Math.min(400, value));
	internalZoomValue.value = clampedValue;
	applyZoomFromValue(clampedValue);
};

// 获取当前缩放值
const getZoomValue = () => {
	return internalZoomValue.value;
};

/** -------------------工具方法------------------- */
// 清除节点内联样式的辅助方法
const clearNodeInlineStyles = (nodeElement: HTMLElement) => {
	if (!nodeElement) return;
	// 清除节点容器的样式
	nodeElement.style.opacity = '';

	// 清除形状元素的样式
	const shapeElement: HTMLElement | null = nodeElement.querySelector('.smm-node-shape');
	if (shapeElement) {
		shapeElement.style.transform = '';
		shapeElement.style.boxShadow = '';
		shapeElement.style.stroke = '';
		shapeElement.style.setProperty('stroke-width', '0');

		shapeElement.style.zIndex = '';
		shapeElement.style.filter = '';
	}

	// 清除文本元素的样式
	const textElement: HTMLElement | null = nodeElement.querySelector('.smm-node-text');
	if (textElement) {
		textElement.style.fontWeight = '';
		textElement.style.color = '';
	}
};

// 通用节点查找方法（基于nodeCache，nodeCache基于完整数据构建）
const findNodesByCondition = (condition: NodeFindCondition, collectChildren = false) => {
	if (!mindMapInstance.value) {
		return { targetNodes: [], highlightNodeIds: new Set<string>() };
	}

	const cache = nodeCache.value;
	const targetNodeIds = new Set<string>();
	const highlightNodeIds = new Set<string>();

	// 构建排除节点集合
	const excludeSet = new Set(props.excludeNodeList.map((id: string) => String(id)));

	// 根据条件查找节点ID
	if (condition.type === 'id') {
		const nodeIds = Array.isArray(condition.value) ? condition.value : [condition.value];
		nodeIds.forEach((id: string) => {
			// 排除 excludeNodeList 中的节点
			if (cache.nodeMap.has(id) && !excludeSet.has(String(id))) {
				targetNodeIds.add(id);
			}
		});
	} else if (condition.type === 'name') {
		const nodeNames = Array.isArray(condition.value) ? condition.value : [condition.value];
		nodeNames.forEach((name: string) => {
			// 支持模糊匹配
			cache.nameMap.forEach((nodeIds, mapName) => {
				if (mapName.includes(name) || mapName === name) {
					nodeIds.forEach((nodeId) => {
						// 排除 excludeNodeList 中的节点
						if (!excludeSet.has(String(nodeId))) {
							targetNodeIds.add(nodeId);
						}
					});
				}
			});
		});
	} else if (condition.type === 'type') {
		const nodeTypes = Array.isArray(condition.value) ? condition.value : [condition.value];
		nodeTypes.forEach((type: string) => {
			const nodeIds = cache.typeMap.get(type);
			if (nodeIds) {
				nodeIds.forEach((nodeId) => {
					// 排除 excludeNodeList 中的节点
					if (!excludeSet.has(String(nodeId))) {
						targetNodeIds.add(nodeId);
					}
				});
			}
		});
	}

	// 收集目标节点及其子节点ID
	if (collectChildren && internalTreeData.value) {
		// 为每个目标节点收集其子节点
		const collectChildrenForTarget = (node: TreeNodeDataType) => {
			const nodeId = node.data.uid || node.data.id;
			if (!nodeId) return;

			if (targetNodeIds.has(nodeId)) {
				// 收集该节点及其所有子节点
				const collectAllChildren = (n: TreeNodeDataType) => {
					const id = n.data.uid || n.data.id;
					if (id) {
						// 排除 excludeNodeList 中的节点
						if (!excludeSet.has(String(id))) {
							highlightNodeIds.add(id);
						}
					}
					if (n.children && n.children.length > 0) {
						n.children.forEach((child) => {
							collectAllChildren(child);
						});
					}
				};
				collectAllChildren(node);
			}

			// 继续递归查找
			if (node.children && node.children.length > 0) {
				node.children.forEach((child) => {
					collectChildrenForTarget(child);
				});
			}
		};

		collectChildrenForTarget(internalTreeData.value);
	} else {
		// 只收集目标节点本身
		targetNodeIds.forEach((nodeId) => {
			highlightNodeIds.add(nodeId);
		});
	}

	// 根据highlightNodeIds查找对应的节点实例
	const targetNodes: TreeNodeElType[] = [];
	highlightNodeIds.forEach((nodeId) => {
		const nodeInstance = mindMapInstance.value?.renderer.findNodeByUid(nodeId);
		if (nodeInstance) {
			targetNodes.push(nodeInstance);
		}
	});

	return { targetNodes, highlightNodeIds };
};

// 展开相关节点（用于高亮时自动展开收起的节点）
// 参数：nodeIds - 需要展开的节点ID集合
// 参数：centerType - 居中类型：'single' 单个节点居中，'multiple' 整体居中，'none' 不居中
// 参数：targetNodeId - 单个节点居中时的目标节点ID（可选）
// 参数：enableChange - 是否启用布局调整，默认为 true
const expandRelatedNodes = (
	nodeIds: Set<string>,
	centerType: 'single' | 'multiple' | 'none' = 'none',
	targetNodeId?: string,
	enableChange = true
) => {
	// 如果不启用居中，强制设置为 'none'
	const finalCenterType = enableChange ? centerType : 'none';
	if (!mindMapInstance.value || !nodeIds || nodeIds.size === 0) return;

	try {
		// 使用缓存中的父节点映射
		const parentMap = nodeCache.value.parentMap;

		// 收集所有需要展开的父节点ID
		const parentIdsToExpand = new Set<string>();

		// 为每个需要展开的节点，向上查找并收集所有父节点ID
		nodeIds.forEach((nodeId) => {
			let currentId: string | undefined = nodeId;

			// 递归向上查找父节点
			while (currentId) {
				const parentId = parentMap.get(currentId);
				if (parentId) {
					parentIdsToExpand.add(parentId);
					currentId = parentId;
				} else {
					break; // 到达根节点
				}
			}
		});

		// 如果有需要展开的节点，标记待应用的高亮节点和居中信息
		if (parentIdsToExpand.size > 0 && enableChange) {
			pendingHighlightNodes.value = {
				nodeIds,
				centerType: finalCenterType,
				targetNodeId
			};
		} else {
			// 如果没有需要展开的节点，直接应用高亮和居中
			applyHighlight(nodeIds);
			applyCenter(finalCenterType, targetNodeId);
			pendingHighlightNodes.value = null;
			return;
		}

		// 展开所有收集到的父节点
		if (enableChange) {
			parentIdsToExpand.forEach((parentId) => {
				try {
					mindMapInstance.value?.execCommand('EXPAND_ALL', parentId);
				} catch (error) {
					console.warn('展开节点失败:', parentId, error);
				}
			});
		}
	} catch (error) {
		console.error('展开相关节点时出错:', error);
		pendingHighlightNodes.value = null;
	}
};

// 高亮节点集合
const highlightedNodes = ref<Set<string>>(new Set());
// 待应用的高亮节点（用于在展开后应用）
const pendingHighlightNodes = ref<{
	nodeIds: Set<string>;
	centerType: 'single' | 'multiple' | 'none'; // 居中类型：单个节点、多个节点、不居中
	targetNodeId?: string; // 单个节点居中时的目标节点ID
} | null>(null);
// 待执行的居中操作标记（用于在展开后执行居中）
const pendingFitToCenter = ref(false);
// 通用高亮应用方法
const applyHighlight = (highlightNodeIds: Set<string>) => {
	if (!mindMapInstance.value) return;

	highlightedNodes.value = highlightNodeIds;

	// 应用样式 - 使用库的API根据nodeId获取节点实例
	nodeCache.value.allNodeIds.forEach((nodeId) => {
		try {
			// 使用 renderer.findNodeByUid 获取节点实例
			const nodeInstance = mindMapInstance.value?.renderer.findNodeByUid(nodeId);
			if (nodeInstance && nodeInstance.group?.node) {
				const nodeElement = nodeInstance.group.node as HTMLElement;
				if (nodeElement) {
					if (highlightNodeIds.has(nodeId)) {
						// 高亮节点 - 使用多种方式设置样式
						setNodeHighlightStyle(nodeElement, true);
					} else {
						// 弱化其他节点
						setNodeHighlightStyle(nodeElement, false);
					}
				}
			}
		} catch (error) {
			// 节点可能还未渲染（被收起），忽略错误
			console.debug('节点未渲染，跳过高亮:', nodeId, error);
		}
	});
};

// 设置节点高亮样式的通用方法
const setNodeHighlightStyle = (nodeElement: HTMLElement, isHighlight: boolean) => {
	if (!nodeElement) return;

	if (isHighlight) {
		// 方法1: 添加CSS类
		nodeElement.classList.add('node-highlighted');
		nodeElement.classList.remove('node-dimmed');

		// 方法2: 直接设置内联样式作为备选方案
		const shapeElement = nodeElement.querySelector('.smm-node-shape') as HTMLElement;
		const textElement = nodeElement.querySelector('.smm-node-text') as HTMLElement;

		if (shapeElement) {
			// shapeElement.style.transform = 'scale(1.05)';
			// 使用从 SCSS 变量读取的品牌色
			shapeElement.style.boxShadow = `0 6px 20px ${colorBrand.value}`;
			shapeElement.style.setProperty('stroke-width', '2px');
			shapeElement.style.stroke = colorBrand.value;
			shapeElement.style.zIndex = '10';
		}

		if (textElement) {
			textElement.style.fontWeight = '700';
			textElement.style.color = '#2b6cb0';
		}

		// 方法3: 设置自定义属性用于识别
		nodeElement.setAttribute('data-highlight-state', 'highlighted');
	} else {
		// 弱化节点
		nodeElement.classList.add('node-dimmed');
		nodeElement.classList.remove('node-highlighted');

		// 直接设置内联样式
		nodeElement.style.opacity = '0.3';

		const shapeElement = nodeElement.querySelector('.smm-node-shape') as HTMLElement;
		const textElement = nodeElement.querySelector('.smm-node-text') as HTMLElement;

		if (shapeElement) {
			shapeElement.style.filter = 'grayscale(0.5)';
			shapeElement.style.transform = 'scale(0.95)';
		}

		if (textElement) {
			textElement.style.color = '#a0aec0';
		}

		nodeElement.setAttribute('data-highlight-state', 'dimmed');
	}
};

// 应用居中操作
const applyCenter = (centerType: 'single' | 'multiple' | 'none', targetNodeId?: string) => {
	if (!mindMapInstance.value || centerType === 'none') return;

	try {
		if (centerType === 'single' && targetNodeId) {
			// 单个节点居中：使用 GO_TARGET_NODE 命令定位到节点
			const targetNode = mindMapInstance.value.renderer.findNodeByUid(targetNodeId);
			if (targetNode) {
				// 使用 GO_TARGET_NODE 命令定位到节点（如果节点被收起会自动展开）
				mindMapInstance.value.execCommand('GO_TARGET_NODE', targetNode);
			}
		} else if (centerType === 'multiple') {
			// 多个节点：整体居中
			(mindMapInstance.value.view.fit as () => void)();
		}
	} catch (error) {
		console.error('应用居中操作时出错:', error);
	}
};

// 递归获取所有节点
const getAllNodes = (node: TreeNodeElType, nodes: TreeNodeElType[] = []) => {
	if (!node) return nodes;

	nodes.push(node);
	if (node.children && node.children.length > 0) {
		node.children.forEach((child: TreeNodeElType) => {
			getAllNodes(child, nodes);
		});
	}
	return nodes;
};

// 应用节点类型样式（全部节点）
const applyNodeTypeStyles = () => {
	if (!mindMapInstance.value) return;

	const root = mindMapInstance.value.renderer?.root;
	if (!root) return;

	const allNodes = getAllNodes(root);

	allNodes.forEach((node) => {
		applySingleNodeTypeStyle(node);
	});
};

// 应用单个节点类型样式
const applySingleNodeTypeStyle = (node: TreeNodeElType) => {
	if (!node) {
		console.warn('节点为空，无法应用样式');
		return;
	}
	const nodeType = node.nodeData?.data?.type;
	if (!nodeType) {
		console.warn('节点类型为空:', node.uid);
		return;
	}

	const nodeElement = node.group?.node;
	if (!nodeElement) {
		console.warn('节点元素为空:', node.uid);
		return;
	}

	const colorConfig = getNodeColorByType(nodeType);

	// 获取节点的形状元素和文本元素
	const shapeElement: HTMLElement | null = nodeElement.querySelector('.smm-node-shape');

	if (shapeElement && colorConfig.fillColor) {
		shapeElement.style.fill = colorConfig.fillColor;
	} else {
		console.warn(`  - 未找到形状元素`);
	}

	// 保存类型信息到元素属性，便于后续查询
	nodeElement.setAttribute('data-node-type', nodeType);
};

// 根据节点类型获取颜色配置
const getNodeColorByType = (type: string) => {
	// 从 themeConfig 中获取类型颜色配置
	const typeColors = props.themeConfig.typeColors || {};
	return (
		typeColors[type] || {
			fillColor: '#50E3C2',
			textColor: '#ffffff'
		}
	);
};

// 应用多段渐变到所有节点
const applyMultiGradients = () => {
	if (!mindMapInstance.value) return;

	const container = mindMapContainerRef.value;
	if (!container) return;

	// 查找或创建 SVG defs 容器
	const svg = container.querySelector('svg');
	if (!svg) return;

	let defs = svg.querySelector('defs');
	if (!defs) {
		defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
		svg.insertBefore(defs, svg.firstChild);
	}

	const root = mindMapInstance.value.renderer?.root;
	if (!root) return;

	const allNodes = getAllNodes(root);

	allNodes.forEach((node, index) => {
		const nodeLevel = node.isRoot ? 'root' : node.layerIndex === 1 ? 'second' : 'node';
		const gradientConfig = multiGradientConfigs.value[nodeLevel];

		if (gradientConfig && gradientConfig.gradientStops) {
			const gradientId = `multi-gradient-${nodeLevel}-${node.uid || index}`;

			// 创建渐变定义
			createSVGGradient(defs as SVGDefsElement, gradientId, gradientConfig);

			// 应用渐变到节点
			const nodeElement = node.group?.node;
			if (nodeElement) {
				const shapeElement = nodeElement.querySelector('.smm-node-shape');
				if (shapeElement) {
					shapeElement.setAttribute('fill', `url(#${gradientId})`);
				}
			}
		}
	});
};

// 创建 SVG 多段渐变定义
const createSVGGradient = (
	defs: SVGDefsElement,
	gradientId: string,
	config: MultiGradientConfigItem
) => {
	// 检查是否已存在
	const existingGradient = defs.querySelector(`#${gradientId}`);
	if (existingGradient) {
		existingGradient.remove();
	}

	// 创建 linearGradient 元素
	const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
	gradient.setAttribute('id', gradientId);

	// 设置渐变方向
	const [x1, y1, x2, y2] = config.gradientDir;
	gradient.setAttribute('x1', `${x1 * 100}%`);
	gradient.setAttribute('y1', `${y1 * 100}%`);
	gradient.setAttribute('x2', `${x2 * 100}%`);
	gradient.setAttribute('y2', `${y2 * 100}%`);

	// 添加渐变色标
	config.gradientStops.forEach((stop: GradientStop) => {
		const stopElement = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
		stopElement.setAttribute('offset', `${stop.offset * 100}%`);
		stopElement.setAttribute('stop-color', stop.color);
		if (stop.opacity !== undefined) {
			stopElement.setAttribute('stop-opacity', String(stop.opacity));
		}
		gradient.appendChild(stopElement);
	});

	defs.appendChild(gradient);
};

// 检查是否在思维导图区域内的函数
const isInMindMapArea = () => {
	const activeElement = document.activeElement;
	const container = mindMapContainerRef.value;

	if (!container) return false;

	return (
		container.contains(activeElement) ||
		activeElement === container ||
		container.querySelector('svg') === activeElement ||
		activeElement?.closest('.tree-graph-container') === container
	);
};

// 验证节点数据格式
const validateNodeData = (node: NodeDataForAdd) => {
	if (!node || typeof node !== 'object') {
		return { valid: false, error: '节点必须是一个对象' };
	}

	if (!node.id) {
		return { valid: false, error: '节点必须有id属性' };
	}

	if (!node.label) {
		return { valid: false, error: '节点必须有label属性' };
	}

	return { valid: true };
};

// 验证连接数据格式
/* eslint-disable @typescript-eslint/no-unused-vars */
const validateLinkData = (link: LinkDataForAdd) => {
	if (!link || typeof link !== 'object') {
		return { valid: false, error: '连接必须是一个对象' };
	}

	if (!link.source || !link.target) {
		return { valid: false, error: '连接必须有source和target属性' };
	}

	return { valid: true };
};

defineExpose({
	highlightNodeByNodeId,
	highlightNodeAndChildrenByNodeId,
	highlightNodeByNodeName,
	highlightNodeAndChildrenByNodeName,
	highlightNodeByType,
	highlightNodeAndChildrenByType,
	clearHighlight,
	showByLevel,
	addNode,
	addNodes,
	removeNode,
	editNode,
	getCurrentData,
	getMindMapInstance,
	fitToCenter,
	zoomIn,
	zoomOut,
	setZoomValue,
	getZoomValue
});
</script>

<style scoped lang="scss">
@use '@/assets/css/variable.scss' as *;

.tree-graph-container {
	width: 100%;
	height: 100%;
	display: flex;
	flex-direction: column;
	font-family: 'Alibaba PuHuiTi', 'Arial', sans-serif;
	-webkit-user-select: none; /* Safari */
	-ms-user-select: none; /* IE 10+ 和 Edge */
	user-select: none; /* 标准语法 */
	// 将 SCSS 变量暴露为 CSS 自定义属性，供 JavaScript 使用
	--color-brand: #{$color-brand};

	:deep(svg) {
		cursor: grab;
	}

	:deep(svg:active) {
		cursor: grabbing;
	}
}

.tree-graph-canvas {
	flex: 1;
	position: relative;
	overflow: hidden;
	background-color: transparent !important;
}

// 自定义思维导图样式
:deep(.smm-node) {
	font-family: 'Alibaba PuHuiTi', 'Arial', sans-serif;

	// 添加过渡效果，避免高亮切换时闪烁
	transition: opacity 0.4s ease;

	.smm-node-shape,
	.smm-text-node-wrap {
		cursor: pointer;
		// 为形状元素添加过渡效果
		transition: box-shadow 0.4s ease, stroke 0.4s ease, filter 0.4s ease, transform 0.4s ease;
	}

	.smm-node-text {
		// 为文本元素添加过渡效果
		transition: color 0.4s ease, font-weight 0.4s ease;
	}

	// 根节点样式
	&.smm-node-root {
		.smm-node-shape {
			box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
		}
	}

	// 一级节点样式
	&.smm-node-generalization {
		.smm-node-shape {
			box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
		}
	}

	// 高亮节点样式
	&.node-highlighted {
		.smm-node-shape {
			box-shadow: 0 6px 20px $color-brand !important;
			stroke: $color-brand !important;
			z-index: 10 !important;
		}

		.smm-hover-node {
			stroke: $color-brand !important;
		}
		.smm-node-text {
			font-weight: 700 !important;
			color: #2b6cb0 !important;
		}
	}

	// 弱化节点样式
	&.node-dimmed {
		opacity: 0.3 !important;

		.smm-node-shape {
			filter: grayscale(0.5) !important;
			transform: scale(0.95) !important;
		}

		.smm-node-text {
			color: #a0aec0 !important;
		}
	}
}

// 通过自定义属性进行高亮样式设置（只读模式的备选方案）
:deep(.smm-node[data-highlight-state='highlighted']) {
	.smm-node-shape {
		box-shadow: 0 6px 20px $color-brand !important;
		stroke: $color-brand !important;
		z-index: 10 !important;
	}
	.smm-hover-node {
		stroke: $color-brand !important;
	}

	.smm-node-text {
		font-weight: 700 !important;
		color: #2b6cb0 !important;
	}
}

:deep(.smm-node[data-highlight-state='dimmed']) {
	opacity: 0.3 !important;

	.smm-node-shape {
		filter: grayscale(0.5) !important;
		transform: scale(0.95) !important;
	}

	.smm-node-text {
		color: #a0aec0 !important;
	}
}

// 强制隐藏所有可能的文本编辑框
:deep(.smm-text-edit),
:deep(.smm-text-edit-input),
:deep(.smm-text-edit-textarea),
:deep([class*='text-edit']),
:deep([class*='textEdit']) {
	display: none !important;
	visibility: hidden !important;
	opacity: 0 !important;
	pointer-events: none !important;
}

// 右键菜单样式
.context-menu {
	position: fixed;
	background: #ffffff;
	border: 1px solid #e2e8f0;
	border-radius: 8px;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
	z-index: 1000;
	min-width: 180px;
	padding: 8px 0;
	font-family: 'Alibaba PuHuiTi', 'Arial', sans-serif;
	-webkit-user-select: none; /* Safari */
	-ms-user-select: none; /* IE 10+ 和 Edge */
	user-select: none; /* 标准语法 */

	.context-menu-item {
		display: flex;
		align-items: center;
		padding: 10px 16px;
		cursor: pointer;
		transition: all 0.2s ease;
		border: none;
		background: none;
		width: 100%;
		text-align: left;
		font-size: 14px;
		color: #4a5568;

		&:hover {
			background-color: #f7fafc;
			color: #2d3748;
		}

		&.danger {
			color: #e53e3e;

			&:hover {
				background-color: #fed7d7;
				color: #c53030;
			}
		}

		.menu-icon {
			margin-right: 12px;
			font-size: 16px;
			width: 20px;
			text-align: center;
			flex-shrink: 0;
		}

		.menu-text {
			flex: 1;
			white-space: nowrap;
			overflow: hidden;
			text-overflow: ellipsis;
		}
	}

	.context-menu-divider {
		height: 1px;
		background-color: #e2e8f0;
		margin: 8px 0;
	}
}

// 节点信息气泡框样式
.node-tooltip {
	position: fixed;
	background: #ffffff;
	border: 1px solid #e2e8f0;
	border-radius: 8px;
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
	z-index: 999;
	min-width: 180px;
	max-width: 280px;
	padding: 12px 16px;
	font-family: 'Alibaba PuHuiTi', 'Arial', sans-serif;
	pointer-events: auto;
	-webkit-user-select: none;
	-ms-user-select: none;
	user-select: none;

	.tooltip-content {
		.tooltip-title {
			font-size: 14px;
			font-weight: 600;
			color: #2d3748;
			margin-bottom: 6px;
			line-height: 1.4;
			word-break: break-word;
		}

		.tooltip-type {
			font-size: 12px;
			color: #718096;
			line-height: 1.4;
		}
	}

	.tooltip-arrow {
		position: absolute;
		width: 0;
		height: 0;
		border: 6px solid transparent;
		border-top-color: #ffffff;
		bottom: -12px;
		left: 50%;
		transform: translateX(-50%);
		filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.05));
	}

	// 箭头边框（模拟边框效果）
	&::before {
		content: '';
		position: absolute;
		width: 0;
		height: 0;
		border: 7px solid transparent;
		border-top-color: #e2e8f0;
		bottom: -14px;
		left: 50%;
		transform: translateX(-50%);
		z-index: -1;
	}
}
</style>
